package good.idea.data.utils;


import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 文件操作工具类
 *
 * @author wenzhaoming
 */
public class FileUtils {


    public static File saveFile(File file, byte[] data) throws Exception {
        if (data != null) {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(data, 0, data.length);
            fos.flush();
            fos.close();
            return file;
        }
        return null;
    }


    /**
     * 保存文件
     *
     * @param is
     * @param filename
     */
    public static void saveStreamToFile(InputStream is, String filename) {
        File file = new File(filename);
        saveStreamToFile(is, file);
    }

    /**
     * 保存文件流到文件中
     *
     * @param is
     * @param file
     */
    public static void saveStreamToFile(InputStream is, File file) {
        try {
            mkdirs(file.getParent());
            FileOutputStream fos = new FileOutputStream(file);
            saveIntStreamToOut(is, fos);
        } catch (Exception e) {
            String message = "error occured when saving file: {}";
        }
    }

    public static void saveIntStreamToOut(InputStream is, OutputStream os) {
        try {
            int read = 0;
            byte buffer[] = new byte[1024];
            while ((read = is.read(buffer)) != -1) {
                os.write(buffer, 0, read);
            }
            os.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }


    /**
     * 保存字符串到文件中
     *
     * @param content
     */
    public static void saveStrToFile(String content, File file) {
        try {
            mkdirs(file.getParent());
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(content.getBytes());
            fos.flush();
            fos.close();
        } catch (Exception e) {
            String message = "error occured when saving file: {}";
        }
    }

    /**
     * 保存字符串到文件中
     *
     * @param content
     * @param filename
     */
    public static void saveStrToFile(String content, String filename) {
        File file = new File(filename);
        saveStrToFile(content, file);
    }

    /**
     * 獲取文件的byte
     *
     * @param filename
     * @return
     */
    public static byte[] getByte(String filename) {
        File file = new File(filename);
        return getByte(file);
    }

    /**
     * 獲取文件的byte
     *
     * @param file
     * @return
     */
    public static byte[] getByte(File file) {
        try {
            byte[] bytes = null;
            if (file != null) {
                InputStream is = new FileInputStream(file);
                long llen = file.length();
                int len = is.available();
                if (llen > len) {
                    //logger.error("文件太大，无法获取字节:"+llen);
                } else {
                    bytes = new byte[len];
                    is.read(bytes);
                    is.close();
                }
            }
            return bytes;
        } catch (Exception e) {
            return null;
        }
    }

    public static byte[] getByte(InputStream input) {
        try {
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024 * 4];
            int n = 0;
            while (-1 != (n = input.read(buffer))) {
                output.write(buffer, 0, n);
            }
            return output.toByteArray();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 删除目录（文件夹）以及目录下的文件
     *
     * @param path 被删除目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String path) {
        //如果path不以文件分隔符结尾，自动添加文件分隔符
        if (!path.endsWith(File.separator)) {
            path = path + File.separator;
        }
        File dirFile = new File(path);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) break;
            }
            //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 删除单个文件
     *
     * @param filepath 被删除文件的文件路径
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String filepath) {
        try {
            File file = new File(filepath);
            // 路径为文件且不为空则进行删除
            if (file.isFile() && file.exists()) {
                file.delete();
                return true;
            }
            return false;
        } catch (Exception e) {
            //logger.error("删除单个文件失败，路径:"+filepath);
            return false;
        }
    }

    /**
     * 创建文件夹(包括多级文件夹)
     *
     * @param path
     * @return
     */
    public static boolean mkdirs(String path) {
        File file = new File(path);
        if (file.exists()) return false;
        return file.mkdirs();
    }

    /**
     * 判断文件是否存在
     *
     * @param pathname
     * @return
     */
    public static boolean fileExists(String pathname) {
        return new File(pathname).exists();
    }


    public static String readString(InputStream is) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuffer response = new StringBuffer();
            String line = null;
            while ((line = reader.readLine()) != null) {
                response.append(line).append("\n");
            }
            return response.toString();
        } catch (Exception e) {
            return null;
        }
    }

    public static void compressFolder(String sourceFile, String pathName) {
        //被压缩的文件夹
        //压缩结果输出，即压缩包
        FileOutputStream fos = null;
        ZipOutputStream zipOut = null;
        try {
            fos = new FileOutputStream(pathName);
            zipOut = new ZipOutputStream(fos);
            File fileToZip = new File(sourceFile);
            zipFile(fileToZip, fileToZip.getName(), zipOut);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (zipOut != null) {
                    zipOut.close();
                }
                if (fos != null) {
                    fos.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 将fileToZip文件夹及其子目录文件递归压缩到zip文件中
     *
     * @param fileToZip 递归当前处理对象，可能是文件夹，也可能是文件
     * @param fileName  fileToZip文件或文件夹名称
     * @param zipOut    压缩文件输出流
     * @throws IOException
     */
    private static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
        //不压缩隐藏文件夹
        if (fileToZip.isHidden()) {
            return;
        }
        //判断压缩对象如果是一个文件夹
        if (fileToZip.isDirectory()) {
            if (fileName.endsWith("/")) {
                //如果文件夹是以“/”结尾，将文件夹作为压缩箱放入zipOut压缩输出流
                zipOut.putNextEntry(new ZipEntry(fileName));
                zipOut.closeEntry();
            } else {
                //如果文件夹不是以“/”结尾，将文件夹结尾加上“/”之后作为压缩箱放入zipOut压缩输出流
                zipOut.putNextEntry(new ZipEntry(fileName + "/"));
                zipOut.closeEntry();
            }
            //遍历文件夹子目录，进行递归的zipFile
            File[] children = fileToZip.listFiles();
            assert children != null;
            for (File childFile : children) {
                zipFile(childFile, fileName + "/" + childFile.getName(), zipOut);
            }
            //如果当前递归对象是文件夹，加入ZipEntry之后就返回
            return;
        }
        //如果当前的fileToZip不是一个文件夹，是一个文件，将其以字节码形式压缩到压缩包里面
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileName);
        zipOut.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
        fis.close();
    }

}
